// 数据库操作封装：Policy 策略相关
package data

import (
	"io"
	"log"
	"time"

	"github.com/sirupsen/logrus"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	gormLoggerPkg "gorm.io/gorm/logger"
)

// Policy 数据库模型，映射策略表
type Policy struct {
	ID               int         `gorm:"primaryKey" json:"id"`           // 策略id
	Name             string      `json:"name"`                           // 策略名称
	Description      string      `json:"description"`                    // 策略描述
	Protocol         string      `json:"protocol"`                       // 协议（TCP/UDP）
	ListenInterface  string      `json:"listenInterface"`                // 监听网口
	ListenPort       int         `json:"listenPort"`                     // 监听端口
	ProxyAddress     string      `json:"proxyAddress"`                   // 代理地址
	ProxyPort        int         `json:"proxyPort"`                      // 代理端口
	ForwardInterface string      `json:"forwardInterface"`               // 转发网口
	ForwardAddress   string      `json:"forwardAddress"`                 // 转发地址
	ForwardPort      int         `json:"forwardPort"`                    // 转发端口（预留）
	AccessControl    StringArray `json:"accessControl" gorm:"type:text"` // 访问控制（字符串数组，json存储）
	VsysId           int         `json:"vsysId"`                         // 虚拟系统id
	CreatedAt        time.Time   `json:"createdAt"`                      // 创建时间
	UpdatedAt        time.Time   `json:"updatedAt"`                      // 更新时间
}

// 使用一个全局的数据库连接句柄
var PolicyDB *gorm.DB

/////////////////////////////////////////主API///////////////////

// CreatePolicy 新增策略
func CreatePolicy(policy *Policy) error {
	return PolicyDB.Create(policy).Error
}

// DeletePolicy 删除策略
func DeletePolicy(id int) error {
	return PolicyDB.Delete(&Policy{}, id).Error
}

// UpdatePolicy 更新策略
func UpdatePolicy(policy *Policy) error {
	return PolicyDB.Save(policy).Error
}

// GetPolicyByID 查询单条策略
func GetPolicyByID(id int) (*Policy, error) {
	var policy Policy
	err := PolicyDB.First(&policy, id).Error
	return &policy, err
}

// ListPolicy 查询策略列表（分页+模糊查询）
func ListPolicy(pageSize, pageNum int, vsysId int, name string) ([]Policy, int64, error) {
	var list []Policy
	var total int64
	query := PolicyDB.Model(&Policy{}).Where("vsys_id = ?", vsysId)
	if name != "" {
		query = query.Where("name LIKE ?", "%"+name+"%")
	}
	query.Count(&total)
	err := query.Offset((pageNum - 1) * pageSize).Limit(pageSize).Find(&list).Error
	return list, total, err
}

// ////////////////////////////////////判断冲突API////////////////////
// 检查名字是否冲突
func IsNameConflict(name string) (bool, error) {
	//对象是否存在
	var res Policy
	err := PolicyDB.Where("name = ?", name).First(&res).Error
	if err == gorm.ErrRecordNotFound {
		return false, nil // 不冲突
	}
	if err != nil {
		return false, err // 查询出错
	}
	return true, nil // 冲突
}

// 检查同一vsysId下协议、监听网口、监听端口三者是否重复
func IsPolicyConflict(protocol, listenInterface string, listenPort int, vsysId int) (bool, error) {
	var res Policy
	err := PolicyDB.Where("protocol = ? AND listen_interface = ? AND listen_port = ? AND vsys_id = ?", protocol, listenInterface, listenPort, vsysId).First(&res).Error
	if err == gorm.ErrRecordNotFound {
		return false, nil // 不冲突
	}
	if err != nil {
		return false, err // 查询出错
	}
	return true, nil // 冲突
}

// ////////////////////////////////////初始化API////////////////////
// 执行数据库文件初始化数据库并建表---获取连接句柄，报错信息
func InitPolicyDB(filename string) error {
	var err error
	gormLogger := gormLoggerPkg.New(log.New(io.Discard, "", log.LstdFlags), gormLoggerPkg.Config{
		SlowThreshold:             0,
		Colorful:                  false,
		IgnoreRecordNotFoundError: true,
		LogLevel:                  gormLoggerPkg.Warn,
	})
	PolicyDB, err = gorm.Open(sqlite.Open(filename), &gorm.Config{Logger: gormLogger})
	if err != nil {
		return err
	}
	//建表
	err = PolicyDB.AutoMigrate(&Policy{})
	if err != nil {
		logrus.Errorf("创建%v表失败!", "Policy")
	} else {
		logrus.Infof("创建%v表成功!", "Policy")
	}
	return nil
}
